TODO: A way to see the path of the currently selected item in any grouplike
      element. Each item in the path should be a button that, when pressed,
      makes the MAIN grouplike view navigate there.
      (Done!)

TODO: A "shuffle queue" button!
TODO: A "clear queue" button.
      (Done! Press S or C, or choose the option from the menubar.)

TODO: A way to jump to an item with a particular name. Probably press "/".
      It'd be nice if the closest match got highlighted while you were typing.
      (Done!)

TODO: "Queue to play next"... maybe also a cursor in the queue list, which
      would tell after what track to place newly-queued items?
      (Done!)

TODO: Scroll to the selected track once it starts playing when selected from
      the queue.

TODO: process.on('SIGWINCH', () => ...) -- detect terminal resize!!
      (Done!)

TODO: Pressing enter in the queue seems to not be doing the right thing?
      It should NOT move the selected item anywhere in the queue; it should
      just select and play that track.
      (Done!)

TODO: iTunes downloader - test this.

TODO: Warn if no mkfifo (means controls won't work).

TODO: file:// support for crawl-local.
      (Done!)

TODO: Pass YouTube playlist or http://.../playlist.json-like URLs to use them
      as playlists (crawl automatically).
      (Done!)

TODO: There's some weird glitch where, if downloaderArg is missing (=== ""),
      it'll play.. something by Jake Chudnow?? -- Okay, looks like it's using
      ~/.mtui/downloads/<locallink, etc>/ as the directory for where it would
      put the download file (because it's .../localink/ + encode(dlArg) and
      dlArg is empty). The way the cache works is that it checks if there is
      already a file in that directory, and there IS: a directory for another
      track download! But the cache doesn't know this; it just thinks that
      directory is the MP3 file (or whatever). So it returns it. MPV works fine
      if you pass it a directory that contains music files, so in my case,
      72_food (by Jake Chudnow) plays. (That's the first thing returned by
      readdir, I suppose.)
      (Done!)

TODO: Mouse support, obviously.

TODO: Ctrl-O'ing a playlist sets the left-pane's selected index to the second
      item, for some reason. (Regardless of what you had selected before..)

TODO: "Open in new tab" in the Open prompt.

TODO: Inspect the inevitable memory issues that are absolutely 100% sure to
      become a problem with opening playlists on the fly.

TODO: Cancelling the "enter a playlist source" dialog shouldn't also stop the
      current song.
      (Done!)

TODO: Move TabberElement to tui-lib, at some point.

TODO: Make PathElements selectable (again).
      (Done!)

TODO: Make the tabber UI show handy information, like what tab you've got
      selected, how many tabs there are, the usual (same way a browser tabber
      works).
      (Done!)

TODO: A "bookmarked playlists" list in the UI, so you can quickly load up
      playlists you often use. (Let anything go here, like YT playlist URLs,
      file paths, etc.)

TODO: Get rid of "WARNING: unable to extract uploader nickname", which comes
      from youtube-dl.
      (Done!)

TODO: Fix crashes related to the window resizing while a download is occurring
      (i.e. the braille "download spinner" is showing). Very weird!

TODO: Investigate performance issues with very very long ListScrollForms.
      (Done!)

TODO: At some point, putting mtui downloads in ~/.mtui - but preferrably with
      a more humanish structure - would be quite nice..!
      (Done! Yeeeeeeees!!!!!!!!)

TODO: Press "M" to show a context menu. (Done!)

TODO: Figure out a keybinding for Mark (in edit mode) - probably Ctrl-M.
      (I prefer Ctrl to be used for functions that will open a dialog of some
      sort, though..)

TODO: Only show scrollbars if the form is actually scrollable. (This would make
      context menus look better.)

TODO: "Play" (now), in the context menu, should act like a queue-up-next, not a
      queue-at-end. (Done!)

TODO: Make the queue code more sane.
      (Done!)

TODO: Figure out when the "queue" context menu options should immediately play
      the track. Currently, they don't ever initiate playing (besides the
      "Play now" option).
      (Done! Sorta. There are now just "play" and "queue" buttons. These use
      the options chosen ("where" and "order"). Previously, combinations of
      those made up menu options, e.g. "queue at end". Now they're separate
      controls and the play/queue button you pick decides whether they play
      right away or not.)

TODO: A "remove from queue" option for tracks and groups, which removes them
      and their children from the queue.
      (Done!)

TODO: After the end of a shuffled queue, the next song from the group of the
      last track is played (and so on, until the group is empty). This seems
      definitely wrong.
      (Done! At the end of a shuffle queue, it just stops now.)

TODO: Show a preview of where "Jump to" will go while typing.
      (Done!)

TODO: Cancelling "Jump to" should return the selected index to whatever it was
      before.
      (Done!)

TODO: Entering more than one key "at once" into a text input element will only
      move the cursor right by one character, not by the length of the inputted
      text. (This is an issue when pasting or spamming the keyboard.) Should be
      fixed in tui-lib.
      (Done!)

TODO: Pressing space while an "Up (to <group>)" button is selected both
      activates the button and pauses music (because the app detects that the
      space key is pressed). This is definitely wrong (it should do one or the
      other - I'm not too sure which, yet, but probably the latter). (Done!)

TODO: If a track's file is a symlink, the "From:" label should show where it
      links to.

TODO: The "Up (to <group>)" and "(This group has no items)" elements are not
      quite buttons nor grouplike items. They should be more consistent with
      actual grouplike items (i.e. same behavior and appearance), and should
      be less buggy.
      (Done!)

TODO: "Distribute" options in play/queue menu -- "don't distribute", "spread
      (across queue?) evenly", "spread randomly".
      (Done!)

TODO: Investigate how to make "distribute" options work better when the
      currently-playing song is contained in the group to be distributed.

TODO: The "distribute" options shouldn't show up when you've only got a track
      selected! But imagine you already had a "distribute" option selected when
      you open up the menu on a track. Is there a way to not mutate the index
      of the whereControl in that case (until the user changes the option)?
      Like the DS home screen.

TODO: If you remove tracks from the queue that are above the currently selected
      track of the queue, the selection index won't change -- so the actual
      selected track will become something different. No good!
      (Done!)

TODO: Arbitrary queue! I.e, you specify the downloadURL, then it queues that
      item.

TODO: A "distribute children" option (with better wording)! Like manually
      queueing each child group to be distributed evenly one by one, but
      automatic.

      More on that thought...I don't think I want to have "clumps" of like,
      one of a song from EVERY album right at the start and the end, when we
      do that. (Well maybe not the end, but definitely at the start.) If we
      pretend there's "fake" items at the start of the group before we
      distribute it, I think we'll get better results - that fake item will be
      placed at the start, letting the rest of the group get distributed in
      better order. (Of course, the fake item is just an offset in the math.
      It isn't an actual item that will get added to the queue.)

TODO: Remove ALL children before queueing, THEN queue them - including any math
      for distribution. Might give interesting results...or maybe it wouldn't
      be any different. Worth investigating!

TODO: A "play later" option for songs in the queue, identical to distributing
      randomly the single track; if the track is already playing, it should
      skip to the next song before shuffling.
      (Done!)

TODO: Loop one song!
      (Done!)

TODO: Volume controls!
      (Done!)

TODO: Metadata, in memory.
      (Done!)

TODO: Load metadata from storage.
      (Done!)

TODO: Restore metadata, if it's recognized as similar to an old path.
      (Basically: How do we deal with moving files around? We'll also want some
      sort of a manager to get rid of unused metadata, if wanted..... on the
      one hand, it'll be saving precious kilobytes, but on the other, people
      might not want to keep a record of moved or deleted tracks at all, so it
      could actually be useful.)

TODO: Don't store duplicate metadata entries (prereq for tags, custom metadata,
      etc) for the same track. Do it symlink-style -- map downloader arg to
      actual key used for metadata (downloaded file path).
      (Done!)

TODO: Metadata process status bar.
      (Done!)

TODO: Add Vim arrow keys. Please forgive me.
      (Done!)

TODO: Use some other key for toggling loop (besides L), so we can make full use
      of HJKL arrow keys.

TODO: In the queue, remove the track number, if possible! Search if all tracks
      (or a majority?? maybe later if it becomes a problem...) follow the same
      track number format (i.e. start with a number), and if so, remove from
      the displayed name. Otherwise, the number is probably just part of the
      track's actual name and shouldn't be removed.
      (Done!)

TODO: An indicator for the number of tracks in the queue!
      (Done!)

TODO: "Reveal" option in queue listing context menu.
      (Done!)

TODO: A menubar!
      (Done!)

TODO: Make pressing the de-focus menubar key restore the selection even if you
      selected the menubar by clicking on it.

TODO: Make the queue length element react to being very squished.

TODO: Don't close the menubar menus when an option is chosen!
      Instead, reload that menu to reflect the changes. Handy so that you can
      easily press a specific action (e.g. "play later") several times in
      succession.

TODO: Color theme picker!! Make sure to save the choice in ~/.mtui, of course!

TODO: An "interweaved" option in the "order" picker - works like putting every
      sub-group into a new queue, each time distributing evenly, then using
      that as the group to queue according to the "where" picker.

TODO: A "reverse" option in the order picker! Also a "reverse order of groups"
      or something, cuz why not yo.
      (Done!)

TODO: The context menu crashes when the input spans across the screen! Need to
      figure out some kind of "fix layout according to max dimensions" code in
      general - it'd be useful here.

TODO: Work out frame rate shenanigans. :) This is a huge task, though (to get
      it exactly right) - to begin, just make it so telnet and ordinary clients
      get different framerates.
      (Done!)

TODO: Remember the scroll position of each group. This should probably be done
      per-listing, but make sure the data disappears when the listing is
      destroyed (e.g. tab closed)! Have maps on the listings instead of the
      grouplikes themselves.
      (Done!)

TODO: Apparently shift-up/down selecting doesn't keep the selected item within
      the scroll view. Fix that.
      (Done!)

TODO: When you queue a song which is already before the current song / insert
      index in the queue, it ends up being placed one index closer to the end
      than intended. Fix this!
      (Done!)

TODO: A "clear after this track" option. Maybe also a corresponding "clear
      up to this track" option?
      (Done!)

TODO: Maybe also a "pause after this track" option. Worth considering!

TODO: Pay closer attention to the ordering of queue items' context menu...
      I like how it is right now for accessibility to specific menu items
      (play sooner/later immediately under the start position, remove from
      queue one "above" the start pos = at the bottom) -- but it might make
      more logical sense to group 'play sooner', 'play next', and 'remove
      from queue' all into one section.

TODO: Figure out duplicates in the selection system! Right now, it's possible
      to have both a group and its children selected at the same time, which
      actually treats them as separate items in the selection grouplike.
      This /might/ be good for performing an action on a group as well as its
      children, but that seems like a rare case (only relevant to labelling as
      far as I can imagine), and it doesn't seem super intuitive UI-wise right
      now.

      Maybe we could make it so if you have a grouplike selected, then browse
      within it to see its children (or subchildren, etc), those child items
      would be highlighted, but only dimly? The idea is that no highlight = not
      selected; dim highlight = a parent is selected and so actions like
      queuing will apply to this item; full highlight = this item itself is
      selected, so actions that only apply to individual items, like labelling,
      will apply. It's not entirely obvious what this means, but I think it
      more or less makes sense.

      BTW: we'll need a new function, removeDuplicates, for said actions. One
      of those "actions" is actually called just by opening the context menu --
      the tally numbers showing the total tracks selected and the sum duration
      of all of those tracks. Make sure to call removeDuplicates after
      flattenGrouplike. (I considered putting that new behavior of rD into fG,
      but it doesn't seem worth it - better to keep them separate and let us
      explicitly decide when we do or don't want to consider duplicates.)

      (Done! But sort of in the reverse direction: you can't select groups
       themselves anymore; whether they display as selected is based upon if
       all their child tracks are selected. Accordingly, groups can also show
       as "partial" selections, if only some of the tracks are selected.
       Might be worth revisiting, but I think what I've got implemented is
       easier to wrap your head around than this stuff, however cool the ideas
       here probably are.)

TODO: Default to 'after selected track' in context menu, and make pressing Q
      (the shorthand for queuing the selection) act as though that's the
      selected option, instead of queuing at the end of the queue (which is
      really only useful when you're building a queue at the start, assuming
      you don't start by shuffling your entire queue anyway).
      (Done!)

TODO: When grouplike listings are fixLayout'd (e.g. the window is resized),
      make sure the selected input is still visible!
      (Done!)

TODO: If you press any key which should select a particular element of the UI
      (e.g. the menubar) while a context menu is open, currently the context
      menu will close and then restore selection to the element which was
      selected when the menu was opened. This seems to happen after the target
      element is selected; the effect is that any key which is meant to focus
      specific UI parts instead closes the context menu while one is open.
      We already have a key for doing just that (the cancel key, i.e. esc or
      period), so fix this!
      (Done!)

TODO: g/G should work for navigation in context menus! And probably all
      ListScrollForms, tbh, but I'm kinda weary of introducing new behavior
      like that to tui-lib.
      (Done!)

TODO: PageUp/PageDown support is complicated to implement (I've tried) and
      should come eventually, but for now just make Home/End work as aliases
      for g/G. ~~This means making it possible for the keybinding system to let
      a single input function return true for multiple different keys!~~
      Actually, we already had that part implemented. :P
      (Done!)

TODO: Work out the BIGGER framerate shenanigans. Specifically: down with the
      render interval! Or, more literally, get rid of it altogether. Only
      render when we know the on-screen text is going to have changed.
      (Done - Huzzah! We use 0% CPU when not actively updating the screen now.)

TODO: Be more sneaky about how we decide what text to update on the screen,
      in a way which saves us performance. Instead of going through the whole
      ansi.interpret process, predict which regions of the screen are going to
      have updated, and only process those spaces. We can guess reasonably by
      looking at which elements caused the screen to update (keep track of this
      in the Root, through the shouldRenderTo function).

TODO: Create a basic Element class, which DisplayElement extends. We have a lot
      of code related to scheduling displaying stuff on the screen, and it'd be
      nice to keep it more separate from all the basic element logic.
      (Done!)

TODO: toString functions for elements! Handy for debugging.

TODO: Revealing a track shouldn't forcibly position it at the bottom of the
      screen (in grouplike listings that span more than a screen). Don't scroll
      if the item is already visible, and if it's above the current scroll
      area, make it appear at the top of the listing view instead of the
      bottom.
      (Done!)

TODO: Text file support. Yes. Heck yes. Heck hecking yes.
      Read text files contained in your music library folders. If there is a
      file which has the same basename as a track (or group), show a mark on
      the item in grouplike listings, and let it be viewed through an action
      on the context menu. Maybe, just MAYBE, implement editing support too.
      (Done!!! Still some WIP stuff in the text editor library, but this is
       definitely functional as of now.)

TODO: Make 'after selected song' the default in the context menu, too. I miight
      go back on this decision, but I think it's just more convenient in
      general, and if you prefer 'after current song', that option isn't hard
      to discover and select.
      (Done!)

TODO: Investigate why reveal() has distinct support for grouplikes as well as
      tracks - you can't append actual groups to the queue (only their
      flattened children) after all. But if you could -- I think reveal should
      work the same for groups as it does for tracks, i.e. opening the parent
      and then selecting the item.

TODO: Make the menubar work like context menus for keyboard selection, e.g.
      pressing P should select 'Playback' (not bubble to the app element and
      rewind to the previous track).
      (Done!)

TODO: Implement a UI in the playback info pane that shows when multiple players
      exist at once. Make sure it's mouse-interactive, too!
      (Done! Will probably be tweaked / expanded in the future.)

TODO: Add a menu for controlling the multiple-players code through the menubar.
      (Done! Oh gosh this was such a hack.)

TODO: Investigate menubar UX - now that it uses KeyboardSelector, it's very
      comparable in interaction to ContextMenus. To match context menus,
      should we make its selection index reset to zero (i.e. the 'mtui' option)
      whenever it's selected (via the keyboard)?
      (Done! Decided yes.)

TODO: When a telnet client disconnects, the music stops. This shouldn't happen!

TODO: Creating a new music player should base its details (volume, looping
      status) on the player which was selected when it was created.

TODO: Show the number of new entries in the "process (new entries)" label.
      Probably don't show that menu option if there aren't any new entries.
      (Also change it to "new tracks" instead of "new entries"?)

TODO: A "play (in new player)" option in the play menu. It'd be nice to have
      this in the queue's context menu, too.

TODO: "Shuffle queue", "shuffle these tracks" options in the queue's
      context menu?

TODO: It looks like you can't move the currently playing track by re-queuing
      it? Investigate this.

TODO: Fix mtui crashing when you interact with it before the main listing has
      loaded its contents.

TODO: Specific config permissions to view and edit text files.

TODO: I lied when I said I finished text editor stuff. Still to-do:
      Don't show text files which are adjacent (same filename, but .txt) to
      a playable. Instead, show a mark on the listing item. Have a context menu
      option for focusing the text editor.

TODO: Have a context menu option for creating a text file for notes on a
      playable, when there is no existing adjacent file.
      (Done!)

TODO: Delete notes files which are totally empty (or just a single line break).

TODO: Only count *consistently* formatted text, across all tracks in a group,
      as track numbering. See '19 3 In The Morning (Pianokind)' for example -
      it is the only track in the group which is formatted '## # <text>'.
      It does follow the formatting '## <text>' as all other tracks do, so only
      the first digits, and following whitespace, should be removed.
      (Done!)

TODO: Related to the above - always keep at least one word. See CANSLP's new
      release "untitled folder", with tracks named "01 1", "02 2", etc.
      (Done!)

TODO: Update to work with IPC server mpv (and socat).
      (Done!)

TODO: Look into testing ^that on Windows. Remove mkfifo, since it's probably
      no longer necessary!

TODO: Expand selection context menu by pressing the heading button! It should
      show a list of the tracks contained within the selection. Selecting any
      item should reveal that item in the main listing pane.

TODO: Opening the selection contxt menu should show an option to either add or
      remove the cursor-focused item from the selection - this would make
      selection accessible when a keyboard or the shift key is inaccessible.
      (Done!)

TODO: Integrate the rest of the stuff that handles argv into parseOptions.
      (Done!)

TODO: Figure out looping not always working consistently. I've tried to deal
      with this before, but it's been broken since switching to socat. Maybe we
      aren't receiving time data as consistently, or aren't re-applying loop
      when we're supposed to?
      (Update: I'm pretty sure this is from socat messages getting dropped -
       probably by fault of mpv, not socat or mtui.)

TODO: Show how many tracks remain in a queue player's queue, ala "+1" floated
      to the right, behind the playback position/duration indicator.
      (Done!)

TODO: "Lock scroll to cursor" option in queue listing. Will make the listing
      automatically scroll so that the selected element is at the same visual
      Y-position - even when the cursor is moved *not* by the user, e.g. the
      enxt track playing while the current track is selected. This will allow
      the user to reveal a certain number of tracks ahead/behind the current
      track according to their liking. (Keep in mind ends of the listing, where
      the scroll can't be adjusted to match because that would mean scrolling
      past the ends... maybe put a dim background behind the element currently
      occupying the locked position, scrolling such that the selected element
      is at that position whenever doing so doesn't go out of bounds?)
      (Done! This was less work than expected. Dim background not implemented
       because (1) it's more work and (2) I don't want to overcomplicate the
       user interface.)

TODO: Revisit labels and notes features! They're commented out for now :P

TODO: Pressing "Reveal" should focus the main listing. This is prrrrobably a
      case of context menu selection-restoring being a pain.
      (Done!)

TODO: When a track besides the currently playing one is selected in the queue
      listing, display the time either *until the track starts* or *since the
      track ended* appropriately, ala "+03:45" or "-1:32:17", in the queue
      time label (which is positioned at the bottom of the queue listing).
      (Done!)

TODO: In that regard, also change the queue length label (just above the time
      label) to indicate which track is selected --- RELATIVE to the current
      track, ala "40 (+5) / 1032" or "5 (-1) / 10".
      (Done!)

TODO: Deselecting a grouplike listing (e.g. by clicking elsewhere) should hide
      its "jump to" element.
      (Done!)

TODO: A "before selected item" option for in the queue menu!
      (Done!)

TODO: The sorting for library3/C418 seems to be weird???? Could be pointing to
      some bug!
      (Done! Using a better package for sorting now.)

TODO: Selecting a group from the path listing at the bottom of listings should
      make it so the child of that group matching with the path is selected.
      For example: selecting X in W/X/Y/Z would open the directory X and
      select item Y; selecting Z would open the directory Z and select the
      track (or group) which the path element is active on in the first place.
      (Done!)

TODO: UI to change the directory from which mtui reads music by default!

TODO: file/folder browse-select UI 0_0

TODO: Change any "song" terminology to "track" in the UI.
      (Done!)

TODO: Empty groups show as selected, lol!

TODO: Multipage context menu doesn't work well in the queue - fix this by
      adding a multipage heading option (or whatever I called em lol) to the
      queue context menu!

TODO: Names like "10. Banana" don't get cropped! Dots/dashes *after* a number
      apparently don't get caught. Oops.
      (Done!)

TODO: "BAM #45.3 - no" displays as "BAM #45.no" in the queue? Seems wrong!
      (Done!)

TODO: "Challenge 1 (Tricks)" etc in FP World 3 are "Challenge (Tricks)"! Bad.
      (Done!)

TODO: Tabber tab list should be accessible via tab (key).

TODO: Show current index and number of tabs beside tabber tab list.

TODO: The checks for "grouplike"/"track" have been super arbitrary for a long
      time. It'd be nice to just store that info in a plain "type" property,
      and tweak updateGroupFormat/etc to generate that! (Probably also the
      crawlers themselves, but they aren't as big of a priority, and we should
      support opening older playlist formats too.)

TODO: Synchronize items that have been shared with the party upon a new client
      joining. Should be next to (or part of) the initialize-backend command.
      (Done!)

TODO: We currently use a hack to access the original item in the context menu
      for items in the party sources listing. This doesn't make, for example,
      queuing by pressing enter on a track work. We should instead have a way
      to specifically refer to the item "represented" by a line, rather than
      the literal object it's associated with (i.e. the pseudo-track/group
      shared in the sources array).

TODO: Broadcast when a socket disconnects; show a log message and remove their
      shared sources from the UI of other clients.

TODO: Ditto for the server! Not (exclusively) as a broadcast message, though -
      detect if the connection to the server is lost for any reason.

TODO: The validation code for share-with-party sucks! It should be made into a
      separate function which runs recursively, and should be used to validate
      initialize-party too.

TODO: Show debug log messages when validating a command fails! On both server
      and client end.

TODO: Naming a shared sources list should definitely happen in a function.
      (Done!)

TODO: Pressing next track (N) on the last track should start the first track,
      if the queue is being looped.
      (Done!)

TODO: Timestamp files. Oh heck yes.
      (Done!)

TODO: Show the current chunk of a track you're on according to its timestamps,
      in both the queue and the main listing! (Put the playing indicator next
      to both the track itself and the timestamp element.)

      Possibly tricky, but try to make this tie in with the "time since/until"
      indicator thingies at the bottom of the queue listing element too!
      (Done - both parts!)

TODO: Some kind of timestamp indicator in the progress bar area??? E.g, name
      of the current timestamp, and MAYBE some kind of visual breakup of the
      progress bar itself?

TODO: Timestamp editing within mtui itself?????????

TODO: Automatically expand/collapse timestamp lists in the queue sidebar!
      (Done!)

TODO: Apparently, seeking to a timestamp under a previous track in the queue
      doesn't respect the current queue order (i.e. it sticks the track after
      the current track). Definitely a bug!
      (Done - fixed!)

TODO: Next/previous buttons should seek between timestamps if there are more
      within the same track.
      (Done!)

TODO: Should skipping back to a previous track with timestamps automatically
      seek to the final timestamp within that track? I'm undecided, but at the
      moment leaning *slightly* towards "no". I may be biased due to it is
      harder to code that behavior though! :P

TODO: The timestamp comment regex should probably skip dashes and other common
      punctuation between the timestamp itself and the comment!

TODO: Pressing ^L to locate the currently playing track (in the queue listing)
      should focus the current timestamp, if there is one.

TODO: I don't think "jump to" (/) works with timestamp items, lol.

TODO: "Alphabetize order of groups" order option. Listen to the releases of
      an artist, or your whole library, alphabetically - or prefix group names
      with the date of release and play works chronologically! Or do whatever
      other shenanigansy inline metadata you like.
      (Done!)

TODO: "Reveal in queue" option in the context menu for tracks that are part of
      the queue! Also, rename existing "Reveal" option to "Reveal in library".
      (Done!)

TODO: Timestamps which have a timestampEnd property (all of them I think?)
      should display their duration in the right column.

TODO: Read timestamps as JSON when the file extension is .json. (Right now
      any .timestamps.json file is ignored!)

TODO: "Remove from queue" seems to always restore the cursor to a non-timestamp
      input. This might be an issue with other queue-modifying actions too!

TODO: The "From: <downloaderArg>" text in the playback info element *does* cut
      off its text in an attempt to not go outside the screen bounds... but it
      goes over the info pane edges anyway, so there's probably a math issue
      there.

TODO: "Play later" has a slight chance of keeping the track in the same place,
      which is accentuated when there's only a couple tracks left in the queue.

TODO: "Loop mode" should be an option under the Queue menu, not Playback.
      (Done!)

TODO: "Loop mode" setting should be displayed in the queue's length label!
      Probably on the same line as ex. "2 / 3", and only when the currently
      playing track is selected.
      (Done!)

TODO: "Clear past current" and "clear up to current" should probably be visible
      from the Queue menu!

TODO: The queue length lebel is kinda busy, and doesn't fit everything so well
      on thinner screens. That should get checked out!
      (Done!)

TODO: When the last track in the queue finishes playing and the queue is set to
      shuffle, the currently selected index in the queue listing won't be moved
      to the new first track (so, reset to zero). The cursor just ends up on
      whatever track had been the last in the queue (which is obviously now in
      some random location - even possibly the first track, but usually not).
      I have a feeling this is the result of shuffling first - which updates
      the selected index to go to wherever the last track ended up - and then
      playing the first track, but not moving the cursor back to the start
      because it's apparently not at the end anymore. But I could be totally
      misremembering how this code works. :P --- Nope not even related LOL.
      Good guess though! We don't even have to worry about that situation, with
      the way selecting the new playing track works. It checks against the
      track which *was* playing... but that was getting cleared to make the
      shuffle work properly (applying to the whole queue instead of just the
      stuff past the current track, which is nothing when you're at its end).
      Now we just use a flag to ignore the current playback position. Since the
      currently playing track is retained for the 'playing track' event, the
      existing code does the rest of the work and selects the newly playing
      track (whatever's been shuffled to the start) all on its own!
      (Done!)

TODO: Apparently pressing any key while the UI is booting up will make the
      screen totally black and unresponsive (and apparently inactive) until the
      screen is resized. I think we're interrupting a control sequence somehow,
      and that isn't being handled very well?

TODO: Pressing escape while you've got items selected should deselect those
      items, rather than stop playback! ...Or SHOULD IT??? Well, yes. But it's
      still handy to not be locked out of stopping playback altogether.
      Alternative: clear the selection (without stopping playback) only if the
      cursor is currently on a selected item.

TODO: GHOST BACKEND for socket server... the main thing is syncing duration
      data. It sucks to have the player, like, actually be tied to a specific
      instance of MPV or whatever, so we'd use a ~ghost player~ which supports
      all the usual interfaces and lies about its current playback time. Yay!
      (Partway: The ghost player exists now, and the backend and UI handle it!
       Just need to hook up a "dummy" backend for the server, with ghost player
       and duration metadata received from socket clients.)

TODO: There should be a way for the server to handle disputes between two
      clients disagreeing on the duration of a track. Options could include,
      for example, "longest": always wait for everyone to be done playing;
      "shortest": don't wait for anyone to be done (past a 1 second threshold
      or whatever), just skip to the next track almost right away; and "first",
      where duration just depends on whoever shared the track. This can all be
      done without everyone sharing their own playback duration, which is kinda
      wasteful; it would be controlled totally by the server deciding when to
      send out events to start the next track, and in reaction only to the
      clients' own "done playing" events (or the GHOST PLAYER reaching the
      playback time provided when the track was first shared).

TODO: Implement a waaaay better socat system, particularly one which waits for
      feedback when a command is sent and returns that. This has to be special-
      coded for mpv since there isn't a generalized standard, so it should make
      use of the existing Socat class, not replace it outright.

TODO: Use above socat system to keep "pinging" the socket until a response is
      received - mpv doesn't make the socket immediately available. I think if
      we wait for a pong response before allowing any actual commands to go
      through, we can avoid weirdness with commands being dropped beacuse they
      were sent too early. For now we just use a time-based delay on the base
      Socat class, which is a hack.
